package com.example.springboot_mvc_demo.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.springboot_mvc_demo.utils.AjaxResult;
import com.example.springboot_mvc_demo.utils.OkHttpUtils;
import lombok.Data;
import okhttp3.Call;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;


@SuppressWarnings({"unchecked", ""})
@RestController
@RequestMapping("/okhttpdemo")
public class OkHttpClientDemo {
    private static final Logger log = LoggerFactory.getLogger(OkHttpClientDemo.class);
    public static final String url_head = "http://localhost:7000";

    @GetMapping("/getMsg")
    public Object getMsg() throws IOException, Exception {


        OkHttpUtils.GetVal<String> async = OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/getMsg".trim())
                .get()
                .async();

        String result = OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/getMsg".trim())
                .get()
                .sync();
        JSONObject jsonObject = JSONObject.parseObject(result);
        String val = async.syncGetVal();
        return jsonObject;
    }

    @GetMapping("/getList")
    public Object getList(Map student) throws Exception {
        AjaxResult sync = OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/list".trim())
                .addParam("name", student.get("name"))
                .addParam("age", student.get("age"))
                .get()
                .sync(AjaxResult.class);
        return sync;
    }

    @GetMapping("/listJson")
    public Object listJson(@RequestParam HashMap map) throws Exception {
        OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/listJson".trim())
                .addParam("name", map.get("name"))
                .addParam("age", map.get("age"))
                .post(true)
                .sync(AjaxResult.class);
        return map;
    }


    @GetMapping("/downFile")
    public Object listJson(String path) throws Exception {
        byte[] bytes = OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/downFile".trim())
                .addParam("path", path)
                .post(false)
                .syncInputStream();

        return "ok";
    }

    /**
     * 异步回调
     */
    @GetMapping("/syncCallBack")
    public Object syncCallBack(@RequestParam HashMap map) {
        CompletableFuture<String> future = new CompletableFuture<>();

        OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/listJson".trim())
                .addParam("name", map.get("name"))
                .addParam("age", map.get("age"))
                .post(true)
                .async(new OkHttpUtils.ICallBack() {
                    @Override
                    public void onSuccessful(Call call, String data) {
                        future.complete(data); // 完成Future并设置结果值
                    }

                    @Override
                    public void onFailure(Call call, String errorMsg) {
                        future.completeExceptionally(new RuntimeException(errorMsg)); // 完成Future并设置异常
                    }
                })
        ;
        try {
            String body = future.get(7, TimeUnit.SECONDS);
            log.info("body:{}", body);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            log.error("time out", e);
        }
        return "ok";
    }

    /**
     * 测试使用json传输文件
     * 可以，需要转为base64，大文件推荐form
     */
    @GetMapping("/uploadByJson")
    public Object uploadByJson(FileObject2Json fileObject) throws Exception {

        fileObject.setFiles(Base64.getEncoder().encodeToString(fileObject.getMultipartFile().getBytes()));
        fileObject.setFileName(fileObject.getMultipartFile().getOriginalFilename());
        cn.hutool.json.JSONObject entries = JSONUtil.parseObj(fileObject);
        String sync = OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/uploadFileByJson".trim())
                .addParam(entries)
                .post(true)
                .sync();

        return "ok";
    }

    /**
     * 测试form 传输文件
     */
    @GetMapping("/uploadByForm")
    public Object uploadByForm(FileObject2Form fileObject) throws Exception {
        fileObject.setFiles(fileObject.multipartFile.getBytes());
        fileObject.setFileName(fileObject.getMultipartFile().getOriginalFilename());
        Map<String, Object> map = BeanUtil.beanToMap(fileObject);
        map.put("files", fileObject.multipartFile);


        String sync = OkHttpUtils.builder()
                .url(url_head + "/api/v1/msg/uploadFileByForm".trim())
                .addParam(map)
                .formFilePost()
                .sync();

        return "ok";
    }


    @Data
    public static class FileObject2Json {
        String files;
        String fileName;
        String savePath;
        transient MultipartFile multipartFile;
    }

    @Data
    public static class FileObject2Form {
        String fileName;
        String savePath;
        transient MultipartFile multipartFile;
        byte[] files;
    }

}
